

use crate::User;
use jwt_simple::prelude::*;

const JWT_DURATION: u64 = 60 * 60 * 24 * 7; //1 week
const JWT_ISS: &str = "chat_server";
const JWT_AUD: &str = "chat_web";


pub struct EncodingKey(Ed25519KeyPair);

pub struct DecodingKey(Ed25519PublicKey);

impl EncodingKey {
    pub fn load(pem: &str) -> Result<Self,jwt_simple::Error> {
        Ok(Self(Ed25519KeyPair::from_pem(pem)?))
    }

    pub fn sign(&self,user: impl Into<User>) -> Result<String,jwt_simple::Error>{
        let claims = Claims::with_custom_claims(user.into(),Duration::from_secs(JWT_DURATION))
            .with_issuer(JWT_ISS)
            .with_audience(JWT_AUD);
        self.0.sign(claims)
    }
}

impl DecodingKey {
    pub fn load(pem: &str) -> Result<Self,jwt_simple::Error> {
        Ok(Self(Ed25519PublicKey::from_pem(pem)?))
    }

    pub fn verify(&self,token: &str) -> Result<User,jwt_simple::Error>{
        let opts = VerificationOptions {
            allowed_issuers: Some(HashSet::from_strings(&[JWT_ISS])),
            allowed_audiences: Some(HashSet::from_strings(&[JWT_AUD])),
            ..Default::default()    
        };
        let claims: JWTClaims<User> = self.0.verify_token(token,Some(opts))?;
        Ok(claims.custom)
    }
}
